#include <stdint.h>
#include <string.h>
#include "UnitTest++.h"
#include "tropicssl/aes.h"

struct AESFixture
{
  static const uint8_t credentials[40];
  static const uint8_t ciphertext[32];
  static const uint8_t plaintext[32];
};

const uint8_t AESFixture::credentials[40] = {
  0x50, 0x8e, 0x8a, 0xfd, 0x78, 0x73, 0x23, 0x38,
  0x67, 0xd6, 0x56, 0xc0, 0xca, 0x46, 0x04, 0x8e,
  0x0a, 0xbb, 0x06, 0xe3, 0x9b, 0xc5, 0x7e, 0x2c,
  0x9b, 0xce, 0x0b, 0xdf, 0xc5, 0x52, 0xc8, 0x2d,
  0xf6, 0x48, 0x0d, 0x23, 0xc5, 0x0e, 0x2d, 0x6d };

const uint8_t AESFixture::ciphertext[32] = {
  0xcf, 0x05, 0x07, 0x47, 0x67, 0x64, 0x15, 0x8c,
  0x7b, 0x63, 0xd0, 0x4c, 0x9d, 0x17, 0xe0, 0x12,
  0xc2, 0xc1, 0x84, 0x10, 0x5b, 0xdd, 0x5e, 0x36,
  0xb8, 0xad, 0x8f, 0x61, 0xdb, 0x7e, 0x85, 0xd1 };

const uint8_t AESFixture::plaintext[32] = {
  0x53, 0x75, 0x70, 0x65, 0x72, 0x20, 0x73, 0x65,
  0x63, 0x72, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x73,
  0x73, 0x61, 0x67, 0x65, 0x0a, 0x0b, 0x0b, 0x0b,
  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };


TEST_FIXTURE(AESFixture, SuccessfullyDecryptsOpenSSLExample)
{
  unsigned char buf[32];
  memcpy(buf, ciphertext, 32);

  unsigned char iv[16];
  memcpy(iv, credentials + 16, 16);

  aes_context ctx;
  aes_setkey_dec(&ctx, credentials, 128);
  aes_crypt_cbc(&ctx, AES_DECRYPT, 32, iv, buf, buf);

  CHECK_ARRAY_EQUAL(plaintext, buf, 32);
}

TEST_FIXTURE(AESFixture, EncryptsSameAsOpenSSL)
{
  uint8_t buf[32];
  memcpy(buf, plaintext, 32);

  unsigned char iv[16];
  memcpy(iv, credentials + 16, 16);

  aes_context ctx;
  aes_setkey_enc(&ctx, credentials, 128);
  /* Note length 21, without PKCS #7 padding */
  aes_crypt_cbc(&ctx, AES_ENCRYPT, 21, iv, buf, buf);

  CHECK_ARRAY_EQUAL(ciphertext, buf, 32);
}

TEST(AESSelfTestSucceeds)
{
  CHECK_EQUAL(0, aes_self_test(0));
}
